﻿using System;
using System.Collections.Generic;
using System.Reflection;
using Vbyte.DataSource.Utility;
using Vbyte.Extension;

namespace Vbyte.DataSource.Cache
{
    /// <summary>
    /// 基于对象属性绑定的标志
    /// </summary>
    [Serializable]
    public class PropertyBindIdentity
    {
        /// <summary>
        /// 初始化一个指定属性名称的值绑定
        /// </summary>
        /// <param name="propName">属性名称</param>
        /// <param name="val">该属性的值</param>
        public PropertyBindIdentity(string propName, object val)
        {
           this[propName] = val;
        }

        /// <summary>
        /// 使用JSON序列化属性标志对象
        /// </summary>
        /// <param name="jsonBindObj">JSON序列化字符</param>
        public PropertyBindIdentity(string jsonBindObj)
        {
            if (string.IsNullOrEmpty(jsonBindObj))
            {
                throw new InvalidOperationException("JSON绑定实例对象的字符串不能为空或null！");
            }
            JSONParse jParse = new JSONParse(jsonBindObj);
            PropBindDict = jParse.GetJsonDictionary();
        }

        private Dictionary<string, object> PropBindDict = new Dictionary<string, object>();

        /// <summary>
        /// 判定指定属性名称是否存在值
        /// </summary>
        /// <param name="propName">属性名称</param>
        /// <returns></returns>
        public bool HasValue(string propName)
        {
            return PropBindDict.ContainsKey(propName);
        }

        /// <summary>
        /// 获取指定属性名称的值
        /// </summary>
        /// <typeparam name="T">值模板数据类型</typeparam>
        /// <param name="propName">属性名称</param>
        /// <returns>指定属性名称的值</returns>
        public T GetValue<T>(string propName)
        {
            object val = this[propName];
            if (val != null)
            {
                Type valType = val.GetType();
                if (valType != typeof(T) && valType.GetInterface(typeof(IConvertible).FullName) != null)
                {
                    val = Convert.ChangeType(val, typeof(T));
                }
                return (T)val;
            }
            return default(T);
        }

        /// <summary>
        /// 获取属性绑定的配置词典
        /// </summary>
        /// <returns></returns>
        public Dictionary<string, object> GetObjectDictionary()
        {
            return PropBindDict;
        }

        /// <summary>
        /// 获取或设置属性绑定键名的值
        /// </summary>
        /// <param name="key">属性键名称</param>
        /// <returns>如果存在该值则返回或更新，不存在则添加或放回为null。</returns>
        public object this[string key]
        {
            get
            {
                return PropBindDict[key];
            }

            set
            {
                if (!HasValue(key))
                {
                    PropBindDict.Add(key, value);
                }
                else
                {
                    PropBindDict[key] = value;
                }
            }
        }

        /// <summary>
        /// 使用可替换的其他URI地址绑定数据的判断设置(远程交互、数据缓存使用)
        /// </summary>
        public bool UseAlternateURIBind { get; set; } 


        /// <summary>
        /// 验证并绑定实例的相关属性值
        /// </summary>
        /// <param name="instanceType">实例类型</param>
        /// <param name="instance">要绑定的目标实例</param>
        public void BindInstance(Type instanceType, object instance)
        {
            foreach (string key in PropBindDict.Keys)
            {
                PropertyInfo pi = instanceType.GetProperty(key);
                if (pi == null)
                {
                    throw new InvalidOperationException("属性名[" + key + "]在指定实例类型[ " + instanceType.FullName + " ]中不存在！");
                }
                else
                {
                    if (PropBindDict[key] != null && pi.PropertyType != PropBindDict[key].GetType())
                    {
                        pi.SetValue(instance, Convert.ChangeType(PropBindDict[key], pi.PropertyType), null);
                    }
                    else
                    {
                        pi.SetValue(instance, PropBindDict[key], null);
                    }
                }
            }
        }

        /// <summary>
        /// 获取当前实例标志的JSON格式
        /// </summary>
        /// <returns>实例标志的JSON格式</returns>
        public override string ToString()
        {
            return SerializationExtension.ToJSON(PropBindDict);
        }
    }

}
